package se.webbzon.oschi01.j3d;

import java.util.ArrayList;
import java.util.Iterator;

import javax.media.j3d.Node;
import javax.media.j3d.OrderedGroup;

/**
 * This class is an extension of the Java3D class javax.media.j3d.OrderedGroup.
 * The AutoOrderedGroup has a method addChild(Node child, int childOrder) which
 * orders the child nodes automatically after an order number. The child node 
 * with the highest order will be rendered last. The order does not have to
 * be continuous.   
 * 
 * @version	1.0.0.0 Jun 27, 2013
 * @author	Oscar Hinrichsen (oschi01)
 * @see 	OrderedGroup
 */
public class AutoOrderedGroup extends OrderedGroup {
	
	// An array list containing the order numbers of the children
	private final ArrayList<Integer> orderList;
	
	/*============================================================
	Constructors
	============================================================*/
	
	/** Constructs and initializes a new AutoOrderedGroup node object. **/
	public AutoOrderedGroup() {
		orderList = new ArrayList<Integer>();
		this.setCapability(ALLOW_CHILD_INDEX_ORDER_READ);
		this.setCapability(ALLOW_CHILD_INDEX_ORDER_WRITE);
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Not supported for AutoOrderedGroup. **/
	@Override public void addChild(Node child, int[] childIndexOrder) {}
	
	@Override public void addChild(Node child) {
		addChild(child,0);
	}
	
	/** Appends the specified child node to this group node's list of children.
	 * The child will be automatically ordered in the group with the parameter
	 * childOrder. The child with the highest order will be rendered last.
	 * 
	 * @param child			the child to add to this node's list of children
	 * @param childOrder	the order of the child node
	 * @since 1.0.0.0
	 */
	public void addChild(Node child, int childOrder) {
		final int children = numChildren();
		if (children == 0) {
			// The group is empty
			orderList.add(childOrder);
			super.addChild(child, new int[] {0});
			
		} else {
			// The group has children
			final Iterator<Integer> it = orderList.iterator();
		
			int index = 0;
		
			while (it.hasNext()) {
				int order = it.next();
				if (order > childOrder)
					break;
				else
					index++;
			}
		
			orderList.add(index, childOrder);
			int[] oldIndexArray = getChildIndexOrder();
			int[] newIndexArray = new int[children+1];
			System.arraycopy(oldIndexArray, 0, newIndexArray, 0, index);
			newIndexArray[index] = children;
			System.arraycopy(oldIndexArray, index, newIndexArray, index+1, children-index);
			
			super.addChild(child, newIndexArray);
		}
	}
	
	/** Not supported for AutoOrderedGroup. **/
	@Override public void insertChild(Node child, int index) {}
	
	@Override public void removeAllChildren() {
		orderList.clear();
		super.removeAllChildren();
	}
	
	@Override public void removeChild(int index) {
		orderList.remove(index);
		super.removeChild(index);
	}
	
	@Override public void removeChild(Node child) {
		int i = indexOfChild(child);
		if (i >= 0)
			removeChild(i);
	}
	
	/** Not supported for AutoOrderedGroup. **/
	@Override public void setChild(Node node, int index) {}
	
	/** Not supported for AutoOrderedGroup. **/
	@Override public void setChildIndexOrder(int[] childIndexOrder) {}
	
}
